from logging import fatal
from fastapi import HTTPException, Header
from typing import Optional
from datetime import datetime, timedelta
from util.const import SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_HOURS
from jose import jwt

from util.my_exceptions import TokenException


def create_token(data: dict, expires_delta: Optional[timedelta] = None):
    """
    生成token函数
    :param data: 需要进行JWT令牌加密的数据（解密的时候会用到）
    :param expires_delta: 令牌有效期
    :return: token
    """
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        # expire = datetime.utcnow() + timedelta(hours=2)
        expire = datetime.utcnow() + timedelta(hours=ACCESS_TOKEN_EXPIRE_HOURS)
    # 添加失效时间
    to_encode.update({"exp": expire})
    # SECRET_KEY：密钥
    # ALGORITHM：JWT令牌签名算法
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def check_token(authorization: Optional[str] = Header(None)):
    """
    解析token
    :param authorization: token字符串
    :return: username
    """
    token = authorization
    try:
        payload = jwt.decode(token, SECRET_KEY, ALGORITHM)
        username: str = payload.get("sub")
        # 通过解析得到的username并返回
        if username:
            return username
        # raise HTTPException(status_code=401, detail='token错误')
        raise TokenException(code=401, msg='token错误', data=None)
    except jwt.ExpiredSignatureError:
        # raise HTTPException(status_code=401, detail='token已过期')
        raise TokenException(code=401, msg='token已过期', data=None)
    except jwt.JWTError:
        # raise HTTPException(status_code=401, detail='token验证失败')
        raise TokenException(code=401, msg='token验证失败', data=None)


# def check_jwt_token(token: Optional[str] = Header("")):
#     """
#     验证token
#     :param token:
#     :return: 返回用户信息
#     """
#     try:
#         payload = jwt.decode(token, SECRET_KEY, algorithms=ALGORITHM)
#         username: str = payload.get("sub")
#         # 通过解析得到的username,获取用户信息,并返回
#         return users_db.get(username)
#     except (jwt.JWTError, jwt.ExpiredSignatureError, ValidationError):
#         raise HTTPException(
#             status_code=status.HTTP_401_UNAUTHORIZED,
#             detail={
#                 'code': 5000,
#                 'message': "Token Error",
#                 'data': "Token Error",
#             }
#         )
